package com.steven.team.service

import com.alibaba.fastjson.JSONObject
import com.mysql.cj.jdbc.MysqlDataSource
import com.steven.team.pojo.MatchInfo
import com.steven.team.dao.MatchDao
import com.steven.team.dao.UserDao
import com.steven.team.utils.RedisUtil
import com.steven.team.utils.ResultUtils
import com.steven.team.utils.makeRes
import org.apache.mahout.cf.taste.impl.model.jdbc.MySQLJDBCDataModel
import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender
import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity
import org.apache.mahout.cf.taste.model.DataModel
import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood
import org.apache.mahout.cf.taste.recommender.UserBasedRecommender
import org.apache.mahout.cf.taste.similarity.UserSimilarity
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
open class MatchServiceImp : MatchService {

    @Autowired
    private val matchDao: MatchDao? = null

    @Autowired
    private val userDao: UserDao? = null

    @Autowired
    private val redisUtil: RedisUtil? = null
    private val MAHOUT_KEY = "mahout_key_uid_"

    override fun calculateMatch(uid: Long): JSONObject {
        val json = JSONObject()
        try {
            if (redisUtil!!.exists(MAHOUT_KEY + uid)) {
                val fromRedis = redisUtil.get(MAHOUT_KEY + uid).toString()
                val jsonParse = JSONObject.parseObject(fromRedis)
                return makeRes(ResultUtils.SUCCESS_CODE, jsonParse)
            } else {
                val dataSource = MysqlDataSource()
                dataSource.setUrl("jdbc:mysql://111.231.212.106:10049/contest_data_base?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=TRUE")
                dataSource.user = "root"
                dataSource.password = "wei19990928123"
                dataSource.getConnection("root", "wei19990928123")
                val model: DataModel = MySQLJDBCDataModel(dataSource, "match_history", "uid", "matchId", "preference", "createTime")
                val similarity: UserSimilarity = PearsonCorrelationSimilarity(model)
                val neighborhood: UserNeighborhood = NearestNUserNeighborhood(3, similarity, model)
                val recommender: UserBasedRecommender = GenericUserBasedRecommender(model, neighborhood, similarity)
                val recommendations = recommender.recommend(uid, 5)
                val strList = ArrayList<String>()
                recommendations.forEach {
                    strList.add(it.itemID.toString())
                }
                if (strList.isNotEmpty()) {
                    json["data"] = matchDao!!.searchMatchDetail(strList)
                    redisUtil.set(MAHOUT_KEY + uid, json)
                } else {
                    json["data"] = ArrayList<MatchInfo>()
                }
                return makeRes(ResultUtils.SUCCESS_CODE, json)
            }
        } catch (e: Exception) {
            json["msg"] = e.printStackTrace()
            return makeRes(ResultUtils.SELECT_ERROR, json)
        }
    }

    override fun searchMatchDetailById(uid: Long, id: Long): JSONObject {
        val json = JSONObject()
        try {
            json["data"] = matchDao!!.searchMatchDetailById(id)
            json["isCollected"] = matchDao.selectCollectionsByMatchId(uid, id).isNotEmpty()
            return makeRes(ResultUtils.SUCCESS_CODE, json)
        } catch (e: Exception) {
            json["msg"] = e.printStackTrace()
            return makeRes(ResultUtils.SELECT_ERROR, json)
        }
    }

    override fun addHistory(uid: Long, matchId: Long): JSONObject {
        val json = JSONObject()
        try {
            matchDao!!.addHistory(uid, matchId)
            return makeRes(ResultUtils.SUCCESS_CODE, json)
        } catch (e: Exception) {
            json["msg"] = e.printStackTrace()
            return makeRes(ResultUtils.INSERT_ERROR, json)
        }
    }

    override fun searchTeamByMatch(matchId: Long): JSONObject {
        val json = JSONObject()
        try {
            json["data"] = matchDao!!.searchTeamByMatch(matchId)
            return makeRes(ResultUtils.SUCCESS_CODE, json)
        } catch (e: Exception) {
            json["msg"] = e.printStackTrace()
            return makeRes(ResultUtils.SELECT_ERROR, json)
        }
    }

    override fun searchTop10MatchRecent(): JSONObject {
        val json = JSONObject()
        try {
            json["data"] = matchDao!!.searchTop10MatchRecent(System.currentTimeMillis() - 30L * 24 * 3600000)
            return makeRes(ResultUtils.SUCCESS_CODE, json)
        } catch (e: Exception) {
            json["msg"] = e.printStackTrace()
            return makeRes(ResultUtils.SELECT_ERROR, json)
        }
    }

    override fun searchHistory(uid: Long): JSONObject {
        val json = JSONObject()
        try {
            json["data"] = matchDao!!.searchHistory(uid)
            return makeRes(ResultUtils.SUCCESS_CODE, json)
        } catch (e: Exception) {
            json["msg"] = e.printStackTrace()
            return makeRes(ResultUtils.SELECT_ERROR, json)
        }
    }

    override fun addToCollection(matchId: Long, uid: Long): JSONObject {
        val json = JSONObject()
        try {
            json["data"] = matchDao!!.addToCollection(matchId, uid)
            return makeRes(ResultUtils.SUCCESS_CODE, json)
        } catch (e: Exception) {
            json["msg"] = e.printStackTrace()
            return makeRes(ResultUtils.INSERT_ERROR, json)
        }
    }

    override fun deleteCollectionById(uid: Long, matchId: Long): JSONObject {
        val json = JSONObject()
        try {
            json["data"] = matchDao!!.deleteCollectionById(uid, matchId)
            return makeRes(ResultUtils.SUCCESS_CODE, json)
        } catch (e: Exception) {
            json["msg"] = e.printStackTrace()
            return makeRes(ResultUtils.DELETE_ERROR, json)
        }
    }

    override fun selectCollectionsByUser(uid: Long, lastCreateTime: Long): JSONObject {
        val json = JSONObject()
        try {
            json["data"] = matchDao!!.selectCollectionsByUser(uid, lastCreateTime)
            return makeRes(ResultUtils.SUCCESS_CODE, json)
        } catch (e: Exception) {
            json["msg"] = e.printStackTrace()
            return makeRes(ResultUtils.SELECT_ERROR, json)
        }
    }

    @Transactional
    override fun addMatch(uid: Long, matchInfo: MatchInfo): JSONObject {
        val json = JSONObject()
        try {
            val user = userDao!!.searchUserStatus(uid)
            if (user.isNotEmpty()) {
                val type = user.first().userType
                if (type != "teacher" && type != "admin") {
                    return makeRes(ResultUtils.INSERT_ERROR, json, "身份缺失权限！")
                }
            }
            return if (matchDao!!.searchMatchByNameAndBelong(matchInfo.name, matchInfo.belong).isEmpty()) {
                matchDao.addMatch(matchInfo)
                makeRes(ResultUtils.SUCCESS_CODE, json)
            } else {
                makeRes(ResultUtils.SUCCESS_CODE, json, "比赛已存在！")
            }
        } catch (e: Exception) {
            json["msg"] = e.printStackTrace()
            return makeRes(ResultUtils.INSERT_ERROR, json)
        }
    }
}